package com.fvision.camera.utils;

import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.fvision.camera.bean.FileBean;
import com.serenegiant.usb.USBMonitor;
import com.huiying.cameramjpeg.UvcCamera;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Created by admin on 2016/12/27.
 */

public class CmdUtil {
    private static final String TAG = "cmdutils";
    private USBMonitor.UsbControlBlock mUsbControlBlock;
    private static CmdUtil _instance;

    public static CmdUtil getInstance() {
        if (_instance == null) {
            _instance = new CmdUtil();
        }
        return _instance;
    }


    public void setCamera_version(String camera_version) {
        this.camera_version = camera_version;
    }

    private String camera_version = "";

    public CmdUtil() {
//        this.mUsbControlBlock = controlBlock;
    }

    /**
     * byte数组转为数字，低位在前，高位在后
     *
     * @param bytes
     * @return
     */
    private int byte2int(byte[] bytes) {
        int length = 0;
        if (bytes.length > 0) {
            length += bytes[0] & 0xff;
        }
        if (bytes.length > 1) {
            length += bytes[1] << 8 & 0xffff;
        }
        if (bytes.length > 2) {
            length += bytes[2] << 16 & 0xffffff;
        }
        if (bytes.length > 3) {
            length += bytes[3] << 24 & 0xffffffff;
        }
        return length;
    }

    /**
     * 切换模式
     *
     * @param value 0为normal,1为playback
     */
    public boolean changeMode(int value) {
        Log.e("9527", "changeMode value = " + value);
        byte[] buffer;
        if (value == 0) {
            buffer = new byte[]{(byte) 0x00};
        } else {
            buffer = new byte[]{(byte) 0x01};
        }
        int ret = sendCommand(0x42, 0x00, 0x00, 0x00, buffer.length, buffer);
        return ret >= 0;
    }

    /**
     * 获取文件数  need playback mode
     *
     * @param type 0: DCIM, 正常 1: EVENT, 緊急 2: LOCK, 加鎖 3: JPEG, 拍照
     * @return 文件数 -1为错误
     */
    public int getFileCount(int type) {
        byte[] buffer = new byte[4];
        int ret = sendCommand(0xc2, 0x05, type, 0, 0x04, buffer);
        if (ret > 0) {
            int count = (buffer[0] & 0xff) + (buffer[1] << 8 & 0xffff) + (buffer[2] << 16 & 0xffffff) + (buffer[3] << 24 & 0xffffffff);
            return count;
        }
        return -1;
    }

    public int getFileCount() {
        byte[] buffer = new byte[512];
        int ret = getFileCount(buffer);
        if (ret == 0) {
            int count = (buffer[0] & 0xff) + (buffer[1] << 8 & 0xffff);
            Log.e(TAG, "9527 getFileInfos: count = " + count);
            return count;
        }
        return 0;
    }

    /**
     * 获取文件名  need playback mode
     *
     * @param type  0: DCIM, 正常 1: EVENT, 緊急 2: LOCK, 加鎖 3: JPEG, 拍照
     * @param index 文件索引
     * @return 返回文件名
     */
    public String getFileName(int type, int index) {
        byte[] buffer = new byte[0x40];
        int ret = sendCommand(0xc2, 0x06, type, index, 0x40, buffer);
        if (ret > 0) {
            return new String(buffer).trim();
        }
        return null;
    }

    public List<FileBean> getFileInfos(int type, int start, byte length) {
        byte[] buffer = new byte[468];
        buffer[0] = length;
        int ret = sendCommand(0xc2, 0x06, type, start, buffer.length, buffer);
        Log.e(TAG, "ryujin getFileInfos: ret = " + ret);
        if (ret > 0) {
            List<FileBean> infos = new ArrayList<>();
            int size = 26;
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            SimpleDateFormat dayformat = new SimpleDateFormat("yyyyMMddHH");
            for (int i = 0; i < length; i++) {
                int startindex = size * i;
                byte[] name = new byte[14];
                byte[] time = new byte[12];
                System.arraycopy(buffer, startindex, name, 0, name.length);
                System.arraycopy(buffer, startindex + name.length, time, 0, time.length);
                FileBean info = new FileBean();
                info.fileName = new String(name);
                info.year = time[0] & 0xff + (time[1] << 8) & 0xffff;
                info.month = time[2] & 0xff + (time[3] << 8) & 0xffff;
                info.day = time[4] & 0xff + (time[5] << 8) & 0xffff;
                info.hour = time[6] & 0xff + (time[7] << 8) & 0xffff;
                info.minute = time[8] & 0xff + (time[9] << 8) & 0xffff;
                info.sencond = time[10] & 0xff + (time[11] << 8) & 0xffff;
                String stime = String.format("%04d%02d%02d%02d%02d%02d", info.year, info.month, info.day, info.hour, info.minute, info.sencond);
                try {
                    Date date = dateFormat.parse(stime);
                    info.sorttime = date.getTime();
                    date = dayformat.parse(stime.substring(0, 10));
                    info.dayTime = date.getTime();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                infos.add(info);
            }
            Log.e(TAG, "ryujin getFileInfos: " + infos.toString());
            return infos;
        }
        return null;
    }

    public int getFileInfos() {
        byte[] buffer = new byte[512];
        int ret = getFile(buffer);
        Log.e(TAG, "9527 getFileInfos: ret = " + ret);
        if (ret > 0) {
            return ret;
        }
        return 0;
    }


//    /**
//     * 获取文件信息  need playback mode
//     *
//     * @param type  0: DCIM, 正常 1: EVENT, 緊急 2: LOCK, 加鎖 3: JPEG, 拍照
//     * @param index 文件索引
//     */
//    public FileInfo getFileInfo(int type, int index) {
//        byte[] buffer = new byte[0x10];
//        int ret = sendCommand(0xc2, 0x07, type, index, 0x10, buffer);
//        if (ret > 0) {
//            FileInfo info = new FileInfo();
//            byte[] temp = new byte[4];
//            System.arraycopy(buffer, 0, temp, 0, temp.length);
//            info.resolution = byte2int(temp);
//            System.arraycopy(buffer, 4, temp, 0, temp.length);
//            info.framerate = byte2int(temp);
//            System.arraycopy(buffer, 8, temp, 0, temp.length);
//            info.filelength = byte2int(temp);
//            System.arraycopy(buffer, 12, temp, 0, temp.length);
//            info.filesize = byte2int(temp);
//            return info;
//        }
//        return null;
//    }

    /**
     * 打开文件回放  need playback mode
     *
     * @param type     0: DCIM, 正常 1: EVENT, 緊急 2: LOCK, 加鎖 3: JPEG, 拍照
     * @param filename 文件名
     */
    public boolean playFile(int type, String filename) {
//        byte[] data = new byte[0x40];
//        byte[] buffer = filename.getBytes();
//        System.arraycopy(buffer, 0, data, 0, buffer.length);
//        int ret = sendCommand(0x42, 0x08, type, 0, 0x40, data);
//        return ret >= 0;

        Log.e("9527", "playFile");
        byte[] buffer = new byte[]{(byte) 0x01, (byte) 0x00};
        int ret = sendCommand(0x42, 0x0c, 0x00, 0x00, buffer.length, buffer);
        return ret >= 0;
    }

    public boolean startPlayFile() {
        Log.e("9527", "startPlayFile");
        byte[] buffer = new byte[]{0x01};
        int ret = sendCommand(0x42, 0x03, 0x00, 0x00, buffer.length, buffer);
        return ret >= 0;
    }


    /**
     * 暂停回放   need playback mode
     */
    public boolean pausePlay() {
        int ret = sendCommand(0x42, 0x09, 0, 0, 0, null);
        return ret >= 0;
    }

    /**
     * 停止播放   need playback mode
     *
     * @return
     */
    public boolean stopPlay() {
        int ret = sendCommand(0x42, 0x0a, 0, 0, 0, null);
        return ret >= 0;
    }

    /**
     * 查询剩余播放时间  need playback mode
     *
     * @return 剩余时间秒数
     */
    public int queryRemainingTime() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x0b, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            int time = (buffer[0] & 0xff) + (buffer[1] << 8 & 0xffff) + (buffer[2] << 16 & 0xffffff) + (buffer[3] << 24 & 0xffffffff);
            return time;
        }
        return -1;
    }

    /**
     * 恢复回放  need playback mode
     *
     * @return
     */
    public boolean resumePlay() {
        int ret = sendCommand(0x42, 0x0c, 0, 0, 0, null);
        return ret >= 0;
    }

    /**
     * 设置录制质量
     *
     * @param value 0: 1080P 1: 720P
     * @return
     */
    public boolean setResolution(int value) {
        int ret = sendCommand(0x42, 0x0f, value, 0, 0, null);
        return ret >= 0;
    }

    /**
     * 设置录制时长
     *
     * @param minite 分钟数
     * @return
     */
    public boolean setRecordTime(int minite) {
        int ret = sendCommand(0x42, 0x10, minite, 0, 0, null);
        return ret >= 0;
    }

    /**
     * 设置频率
     *
     * @param value 0: 60Hz 1: 50Hz
     * @return
     */
    public boolean setFrequence(int value) {
        int ret = sendCommand(0x42, 0x11, value, 0, 0, null);
        return ret >= 0;
    }

    /**
     * 拍照
     *
     * @return
     */
    public boolean snapShot() {
        int ret = sendCommand(0x42, 0x14, 0, 0, 0, null);
        return ret >= 0;
    }

    /**
     * 开启录制
     *
     * @return
     */
    public boolean startRecord() {
        Log.e("9527", "startRecord ");
        byte[] buffer = new byte[]{0x01};
        int ret = sendCommand(0, 0x01, 0x00, 0x00, buffer.length, buffer);
        return ret >= 0;
    }

    /**
     * 关闭录制
     *
     * @return
     */
    public boolean stopRecord() {
        Log.e("9527", "stopRecord ");
        byte[] buffer = new byte[]{0x00};
        int ret = sendCommand(0x42, 0x01, 0x00, 0x00, buffer.length, buffer);
        return ret >= 0;
    }

    /**
     * 开启或关闭录音
     *
     * @param value 0: disable to record audio 1: enable to record audio
     * @return
     */
    public boolean changeAudioRecord(int value) {
        Log.e("9527", "changeAudioRecord value = " + value);
        String filename;
        if (value == 0) {
            filename = "0";
        } else {
            filename = "1";
        }

        byte[] buffer = filename.getBytes();
        int ret = sendCommand(0x42, 0x06, 0x00, 0x00, buffer.length, buffer);
        return ret >= 0;
    }

    /**
     * 设置曝光度
     *
     * @param value
     * @return
     */
    public boolean setExposure(int value) {
//        byte[] data=new byte[4];
//        data[0]= (byte) (value&0xff);
//        data[1]= (byte) ((value>>8)&0xff);
//        data[2]= (byte) ((value>>16)&0xff);
//        data[3]= (byte) ((value>>24)&0xff);
        int ret = sendCommand(0x42, 0x70, value, 0x00, 0, null);
        return ret >= 0;
    }

    public int getExposure() {
        byte[] data = new byte[4];
        int ret = sendCommand(0xc2, 0x60, 0x00, 0x00, data.length, data);
        if (ret >= 0)
            return byte2int(data);
        return -1;
    }

    /**
     * 格式化存储卡
     *
     * @return
     */
    public boolean formatTFcard() {
        Log.e("9527", "formatTFcard");
        String filename = "1";
        byte[] buffer = filename.getBytes();
        int ret = sendCommand(0x42, 0x17, 0x00, 0x00, buffer.length, buffer);
        return ret >= 0;
    }

    public boolean setCurrentTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int sencond = calendar.get(Calendar.SECOND);
        byte[] data = new byte[0x0c];
        data[0] = (byte) (year & 0xff);
        data[1] = (byte) (year >> 8 & 0xff);

        data[2] = (byte) (month & 0xff);
        data[3] = (byte) (month >> 8 & 0xff);

        data[4] = (byte) (day & 0xff);
        data[5] = (byte) (day >> 8 & 0xff);

        data[6] = (byte) (hour & 0xff);
        data[7] = (byte) (hour >> 8 & 0xff);

        data[8] = (byte) (minute & 0xff);
        data[9] = (byte) (minute >> 8 & 0xff);

        data[10] = (byte) (sencond & 0xff);
        data[11] = (byte) (sencond >> 8 & 0xff);

        Log.e(TAG, "year=" + year + ",month=" + month + ",day=" + day + ",hour=" + hour + ",minute=" + minute + ",sencond=" + sencond);
        int ret = sendCommand(0x42, 0x1c, 0, 0, data.length, data);
        return ret >= 0 && year >= 2000;
    }

    /**
     * 获取视频录制状态 -1 error, 0: no record, 1: recording
     *
     * @return
     */
    public int getVideoRecordState() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x1d, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            if (checkCameraversion("v1.1")) {
                if ((buffer[1] & 0xff) == 0xff) {
                    return buffer[0];
                }
            } else {
                return buffer[0];
            }
        }
        return -1;
    }

    /**
     * 获取摄像头版本
     *
     * @return
     */
    public String getCameraVersion() {
        byte[] buffer = new byte[0x0f];
        int ret = sendCommand(0xc2, 0x49, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            String version = new String(buffer).trim();
            camera_version = version;
            return version;
        }
        return "";
    }

    /**
     * 获取视频录制状态 -1 error, 0: no record, 1: recording
     *
     * @return
     */
    public byte[] getAudioRecordState() {
        byte[] buffer = new byte[0x40];
        int ret = sendCommand(0xc2, 0x1E, 0x214f, 0, buffer.length, buffer);
        if (ret > 0) {
//            int value = (buffer[0] & 0xff) + (buffer[1] << 8 & 0xffff) + (buffer[2] << 16 & 0xffffff) + (buffer[3] << 24 & 0xffffffff);
//            if(value==0x2291){
//                return 1;
//            }else if(value==0x2290){
//                return 0;
//            }
            return buffer;
        }
        return null;
    }

    /**
     * 获取视频录制状态 -1 error, 0: no record, 1: recording
     *
     * @return
     */
    public int getAudioRecordState1() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x1E, 0, 0, buffer.length, buffer);
        if (ret > 0) {
//            int value = (buffer[0] & 0xff) + (buffer[1] << 8 & 0xffff) + (buffer[2] << 16 & 0xffffff) + (buffer[3] << 24 & 0xffffffff);
//            return value;
            if (checkCameraversion("v1.1")) {
                if ((buffer[1] & 0xff) == 0xff) {
                    return buffer[0];
                }
            } else {
                return buffer[0];
            }
        }
        return -1;
    }

    /**
     * 获取TF卡状态
     *
     * @return -1 error, 0: no card or can not be written 1: card exist and ready for writing
     */
    public int getTFState() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x1f, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            if (checkCameraversion("v1.1")) {
                if ((buffer[1] & 0xff) == 0xff) {
                    return buffer[0];
                }
            } else {
                return buffer[0];
            }
        }
        return -1;
    }

    public int getTFState1() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x33, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            return buffer[0];
        }
        return -1;
    }

    private boolean checkCameraversion(String version) {
        if (!TextUtils.isEmpty(camera_version)) {
            String[] versions = camera_version.split("_");
            if (versions.length > 1) {
                return versions[0].toLowerCase().compareTo(version.toLowerCase()) >= 0;
            }
        }
        return false;
    }

    /**
     * 获取gsensor状态
     *
     * @return -1 errro, 0: no event appear, 1: evnt appear
     */
    public int getGsensorState() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x20, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            if (checkCameraversion("v1.1")) {
                if ((buffer[1] & 0xff) == 0xff) {
                    return buffer[0];
                }
            } else {
                return buffer[0];
            }
        }
        return -1;
    }

    public byte[] getAllState() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x55, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            return buffer;

        }
        return null;
    }

    /**
     * 删除文件   need playback mode
     *
     * @param type     0: DCIM, 正常1: EVENT, 緊急 2: LOCK, 加鎖 3: JPEG, 拍照
     * @param filename 文件名
     * @return
     */
    public boolean deleteFile(int type, String filename) {
        byte[] data = new byte[0x40];
        byte[] filedata = filename.getBytes();
        System.arraycopy(filedata, 0, data, 0, filedata.length);
        int ret = sendCommand(0x42, 0x21, type, 0, 0x40, data);
        return ret >= 0;
    }

    /**
     * 获取录制质量
     *
     * @return -1 error, 0: 1080P, 1: 720P
     */
    public int getResolution() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x2f, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            return buffer[0];
        }
        return -1;
    }

    /**
     * 获取录制时长
     *
     * @return 录制时长分钟数，-1为获取失败
     */
    public int getRecordLength() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x30, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            return buffer[0];
        }
        return -1;
    }

    /**
     * 获取频率
     *
     * @return -1 error, 0: 60Hz 1: 50Hz
     */
    public int getFrequence() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x31, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            return buffer[0];
        }
        return -1;
    }

    /**
     * 播放快进  need playback mode
     *
     * @param seconds the time in seconds to seek
     * @return
     */
    public boolean seekPlayTime(int seconds) {
        byte[] data = new byte[0x04];
        data[0] = (byte) (seconds & 0xff);
        data[1] = (byte) (seconds >> 8 & 0xff);
        data[2] = (byte) (seconds >> 16 & 0xff);
        data[3] = (byte) (seconds >> 24 & 0xff);
        int ret = sendCommand(0x42, 0x32, 0, 0, data.length, data);
        return ret >= 0;
    }

    /**
     * 打开读取文件  need playback mode
     *
     * @param type     0: DCIM, 正常1: EVENT, 緊急 2: LOCK, 加鎖 3: JPEG, 拍照
     * @param filename 文件名
     * @return
     */
    public boolean openReadFile(int type, String filename) {
        byte[] data = new byte[0x40];
        byte[] filedata = filename.getBytes();
        System.arraycopy(filedata, 0, data, 0, filedata.length);
        int ret = sendCommand(0x42, 0x50, type, 0, 0x40, data);
        return ret >= 0;
    }

    /**
     * 获取读取文件长度  need playback mode
     *
     * @return 文件字节数，-1 error
     */
    public int getReadFileLenght() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x51, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            int length = (buffer[0] & 0xff) + (buffer[1] << 8 & 0xffff) + (buffer[2] << 16 & 0xffffff) + (buffer[3] << 24 & 0xffffffff);
            return length;
        }
        return -1;
    }

//    /**
//     * 读取数据 need playback mode
//     *
//     * @param offset 第几个包
//     * @return
//     */
//    public DataPaket getFileData(int offset, int length) {
////        int length = 0x0800;
//        byte[] buffer = new byte[length];
//        int ret = sendCommand(0xc2, 0x52, offset, 0, buffer.length, buffer);
//        if (ret > 0) {
//            DataPaket paket = new DataPaket();
//            paket.data = buffer;
//            paket.length = ret;
//            return paket;
//        }
//        return null;
//    }

    /**
     * 关闭文件  need playback mode
     *
     * @return
     */
    public boolean closeReadFile() {
        int ret = sendCommand(0x42, 0x53, 0, 0, 0x00, null);
        return ret >= 0;
    }

    public boolean openStream() {
        byte[] data = {0x0, 0x0, 0x01, 0x01, 0x15, 0x16, 0x05, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, (byte) 0xa4, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0};
        int ret = sendCommand(0x21, 0x01, 0x0002, 0x0200, 0x1a, data);
        return ret >= 0;
    }

    public boolean closeStream() {
        int ret = sendCommand(0x00, 0x01, 0x0000, 0x0083, 0x00, null);
        return ret >= 0;
    }

    /**
     * 设置图像上下翻转
     *
     * @param turn
     * @return
     */
    public boolean setTurnTopBottom(boolean turn) {
        byte[] data = new byte[]{(byte) (turn ? 1 : 0), 0, 0, 0};
        int ret = sendCommand(0x42, 0x45, turn ? 1 : 0, 0x00, 0x04, data);
        return ret >= 0;
    }

    /**
     * 设置图像镜像
     *
     * @param turn
     * @return
     */
    public boolean setTurnLeftRight(boolean turn) {
        byte[] data = new byte[]{(byte) (turn ? 1 : 0), 0, 0, 0};
        int ret = sendCommand(0x42, 0x46, turn ? 1 : 0, 0x00, 0x04, data);
        return ret >= 0;
    }

    /**
     * 设置加解锁
     *
     * @param lock 0解锁，1加锁
     * @return
     */
    public boolean setLock(int lock) {
        Log.e("9527", "setLock");
        String filename = "1";
        byte[] buffer = filename.getBytes();
        int ret = sendCommand(0x42, 0x00, 0x00, 0x00, buffer.length, buffer);//0x48
        Log.e("9527", "ret= " + ret);
        return ret >= 0;
    }

    public int getTurnTopBottom() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x40, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            return buffer[0];
        }
        return -1;
    }

    public int getTurnLeftRight() {
        byte[] buffer = new byte[0x04];
        int ret = sendCommand(0xc2, 0x41, 0, 0, buffer.length, buffer);
        if (ret > 0) {
            return buffer[0];
        }
        return -1;
    }

    private int sendCommand(int requesttype, int request, int value, int index, int length, byte[] data) {
//        if (mUsbControlBlock != null&&mUsbControlBlock.getUsbDeviceConnection()!=null) {
//            return mUsbControlBlock.getUsbDeviceConnection().controlTransfer(requesttype, request, value, index, data, length, 3000);
//        }
        if (UvcCamera.getInstance().isInit()) {
            return UvcCamera.getInstance().sendCmd(requesttype, request, value, index, length, data);
        }
        return -1;
    }

    private int getFile(byte[] data) {
        if (UvcCamera.getInstance().isInit()) {
            return UvcCamera.getInstance().getFile(data);
        }
        return -1;
    }

    private int getFileCount(byte[] data) {
        if (UvcCamera.getInstance().isInit()) {
            return UvcCamera.getInstance().getFileCount(data);
        }
        return -1;
    }

    private void sendCommand(int requesttype, int request, int value, int index, int length, byte[] data, ByteCallback callback) {
        new BulkThread(requesttype, request, value, index, data, length, callback).start();
    }

    class BulkThread extends Thread {
        ByteCallback mCallback;
        int requesttype;
        int request;
        int value;
        int index;
        byte[] data;
        int length;
        private Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (mCallback != null) {
                    mCallback.onCallback((byte[]) msg.obj, msg.arg1 == 0);
                }
            }
        };

        public BulkThread(int requsttype, int request, int value, int index, byte[] data, int length, ByteCallback callback) {
            this.requesttype = requsttype;
            this.request = request;
            this.value = value;
            this.index = index;
            this.data = data;
            this.length = length;
            this.mCallback = callback;
        }

        @Override
        public void run() {
            if (mUsbControlBlock != null) {
                int out = mUsbControlBlock.getUsbDeviceConnection().controlTransfer(requesttype, request, value, index, data, length, 3000);
                if (out >= 0) {
                    Message msg = mHandler.obtainMessage();
                    msg.arg1 = 0;
                    if (out > 0) {
                        msg.obj = data;
                    }
                    mHandler.sendMessage(msg);
                    return;
                }
            }
            Message msg = mHandler.obtainMessage();
            msg.arg1 = -1;
            mHandler.sendMessage(msg);
        }
    }

    class CmdThread extends Thread {
        ByteCallback mCallback;
        int requesttype;
        int request;
        int value;
        int index;
        byte[] data;
        int length;
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (mCallback != null) {
                    mCallback.onCallback((byte[]) msg.obj, msg.arg1 == 0);
                }
            }
        };

        public CmdThread(int requsttype, int request, int value, int index, byte[] data, int length, ByteCallback callback) {
            this.mCallback = callback;
            this.requesttype = requsttype;
            this.request = request;
            this.value = value;
            this.index = index;
            this.data = data;
            this.length = length;
        }

        @Override
        public void run() {
            if (mUsbControlBlock != null) {
                int ret = mUsbControlBlock.getUsbDeviceConnection().controlTransfer(requesttype, request, value, index, data, length, 0);
                Message msg = handler.obtainMessage();
                msg.arg1 = (ret >= 0) ? 0 : -1;
                handler.sendMessage(msg);
                return;
            }
            Message msg = handler.obtainMessage();
            msg.arg1 = -1;
            handler.sendMessage(msg);
        }
    }

    public interface ByteCallback {
        void onCallback(byte[] data, boolean sucess);
    }
}
